﻿using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;

namespace Daq.Devices
{

    public class WebSocketClient : IDisposable
    {
        private WebSocket _ws;
        private System.Timers.Timer _pingTimer;
        private System.Timers.Timer _reconnectTimer;
        private readonly string _serverUrl;
        private readonly int _pingInterval; // ping间隔（毫秒）
        private readonly int _reconnectInterval; // 重连间隔（毫秒）
        private readonly int _maxReconnectAttempts; // 最大重连尝试次数
        private int _currentReconnectAttempt; // 当前重连尝试次数
        private bool _isManualDisconnect; // 是否是手动断开连接
        private bool _isDisposed; // 是否已释放资源
        private readonly Action<string> _onMessage;
        private readonly Action<string> _onError;
        private readonly Action _onOpen;
        private readonly Action _onClose;
        private readonly Action<int, int> _onReconnecting; // 重连尝试回调 (当前尝试次数, 最大尝试次数)
        private readonly Action<bool> _onReconnectSuccess; // 重连成功回调 (是否是首次连接)
        private readonly Action<int, int, string> _onReconnectFailed; // 重连失败回调 (当前尝试次数, 最大尝试次数, 错误信息)
        private readonly SemaphoreSlim _connectionSemaphore = new SemaphoreSlim(1, 1); // 用于同步连接操作

        // 构造函数，接收服务器URL和回调函数
        public WebSocketClient(string serverUrl, int pingInterval = 30000, int reconnectInterval = 5000,
            int maxReconnectAttempts = 10,
            Action<string> onMessage = null,
            Action<string> onError = null,
            Action onOpen = null,
            Action onClose = null,
            Action<int, int> onReconnecting = null,
            Action<bool> onReconnectSuccess = null,
            Action<int, int, string> onReconnectFailed = null)
        {
            _serverUrl = serverUrl;
            _pingInterval = pingInterval;
            _reconnectInterval = reconnectInterval;
            _maxReconnectAttempts = maxReconnectAttempts;
            _currentReconnectAttempt = 0;
            _isManualDisconnect = false;
            _isDisposed = false;
            _onMessage = onMessage;
            _onError = onError;
            _onOpen = onOpen;
            _onClose = onClose;
            _onReconnecting = onReconnecting;
            _onReconnectSuccess = onReconnectSuccess;
            _onReconnectFailed = onReconnectFailed;
        }

        // 异步连接到WebSocket服务器
        public async Task ConnectAsync()
        {
            _isManualDisconnect = false;
            _currentReconnectAttempt = 0;
            await ConnectInternalAsync(false);
        }

        // 内部异步连接方法
        private async Task ConnectInternalAsync(bool isReconnect)
        {
            await _connectionSemaphore.WaitAsync();

            try
            {
                if (_isDisposed)
                    return;

                // 如果已经有活动连接，先关闭
                if (_ws != null && _ws.IsAlive)
                {
                    _ws.Close();
                    await Task.Delay(100); // 给关闭操作一些时间
                }

                // 创建新的WebSocket实例
                _ws = new WebSocket(_serverUrl);

                // 设置消息处理程序
                _ws.OnMessage += (sender, e) =>
                {
                    if (e.IsText)
                    {
                        string message = e.Data;
                        Debug.WriteLine($"接收到文本消息: {message}");
                        _onMessage?.Invoke(message);

                        // 示例：解析JSON消息
                        try
                        {
                            //dynamic parsed = JsonConvert.DeserializeObject(message);
                            //Debug.WriteLine($"解析消息类型: {parsed.type}，内容: {parsed.data}");
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"解析消息失败: {ex.Message}");
                        }
                    }
                    else if (e.IsBinary)
                    {
                        Debug.WriteLine($"接收到二进制消息，长度: {e.RawData.Length}字节");
                        // 处理二进制数据
                    }
                    else if (e.IsPing)
                    {
                        Debug.WriteLine("接收到服务器Ping");
                        // 自动回复Pong，WebSocketSharp会自动处理
                    }
                };

                // 设置错误处理程序
                _ws.OnError += (sender, e) =>
                {
                    Debug.WriteLine($"错误: {e.Message}");
                    _onError?.Invoke(e.Message);

                    // 如果是连接过程中发生错误，触发重连逻辑
                    if (!(_ws?.IsAlive ?? false) && !_isManualDisconnect)
                    {
                        StartReconnectTimer();
                    }
                };

                // 设置连接打开处理程序
                _ws.OnOpen += (sender, e) =>
                {
                    Debug.WriteLine("WebSocket连接已打开");
                    _currentReconnectAttempt = 0;
                    StopReconnectTimer();
                    _onOpen?.Invoke();
                    _onReconnectSuccess?.Invoke(!isReconnect);
                    StartPingTimer(); // 连接打开后启动ping定时器
                };

                // 设置连接关闭处理程序
                _ws.OnClose += (sender, e) =>
                {
                    Debug.WriteLine($"WebSocket连接已关闭，状态码: {e.Code}, 原因: {e.Reason}");
                    _onClose?.Invoke();
                    StopPingTimer(); // 连接关闭后停止ping定时器

                    // 如果不是手动断开连接，触发重连逻辑
                    if (!_isManualDisconnect)
                    {
                        StartReconnectTimer();
                    }
                };

                // 异步连接到服务器
                Debug.WriteLine($"正在连接到 {_serverUrl}");
                await Task.Run(() => _ws.Connect());
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"连接失败: {ex.Message}");
                _onError?.Invoke(ex.Message);

                // 如果不是手动断开连接，触发重连逻辑
                if (!_isManualDisconnect)
                {
                    StartReconnectTimer();
                }
            }
            finally
            {
                _connectionSemaphore.Release();
            }
        }

        // 异步发送消息
        public async Task SendMessageAsync(string message)
        {
            if (_ws == null || !_ws.IsAlive)
            {
                Debug.WriteLine("无法发送消息，连接未建立或已关闭");
                return;
            }

            await Task.Run(() => _ws.Send(message));
            Debug.WriteLine($"发送消息: {message}");
        }

        // 异步发送二进制数据
        public async Task SendBinaryAsync(byte[] data)
        {
            if (_ws == null || !_ws.IsAlive)
            {
                Debug.WriteLine("无法发送二进制数据，连接未建立或已关闭");
                return;
            }

            await Task.Run(() => _ws.Send(data));
            Debug.WriteLine($"发送二进制数据，长度: {data.Length}字节");
        }

        // 异步关闭连接
        public async Task DisconnectAsync()
        {
            _isManualDisconnect = true;
            StopPingTimer();
            StopReconnectTimer();

            if (_ws != null && _ws.IsAlive)
            {
                await Task.Run(() => _ws.Close());
                Debug.WriteLine("主动关闭WebSocket连接");
            }
        }

        // 启动定时Ping
        private void StartPingTimer()
        {
            StopPingTimer(); // 先停止可能存在的旧定时器

            _pingTimer = new System.Timers.Timer(_pingInterval);
            _pingTimer.Elapsed += async (sender, e) =>
            {
                try
                {
                    if (_ws != null && _ws.IsAlive)
                    {
                        await Task.Run(() => _ws.Ping());
                        Debug.WriteLine($"发送Ping: {DateTime.Now}");
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"发送Ping失败: {ex.Message}");

                    // Ping失败可能表示连接已断开，触发重连逻辑
                    if (!_isManualDisconnect)
                    {
                        // 停止当前的ping定时器
                        StopPingTimer();
                        // 触发重连
                        StartReconnectTimer();
                    }
                }
            };
            _pingTimer.AutoReset = true;
            _pingTimer.Start();
        }

        // 停止定时Ping
        private void StopPingTimer()
        {
            if (_pingTimer != null)
            {
                _pingTimer.Stop();
                _pingTimer.Dispose();
                _pingTimer = null;
            }
        }

        // 启动重连定时器
        private void StartReconnectTimer()
        {
            StopReconnectTimer();

            // 如果已经达到最大重连次数，不再尝试重连
            if (_maxReconnectAttempts > 0 && _currentReconnectAttempt >= _maxReconnectAttempts)
            {
                Debug.WriteLine($"已达到最大重连次数 ({_maxReconnectAttempts})，停止重连尝试");
                _onReconnectFailed?.Invoke(_currentReconnectAttempt, _maxReconnectAttempts, "已达到最大重连次数");
                return;
            }

            _currentReconnectAttempt++;
            _onReconnecting?.Invoke(_currentReconnectAttempt, _maxReconnectAttempts);

            Debug.WriteLine($"将在 {_reconnectInterval / 1000} 秒后尝试重连 ({_currentReconnectAttempt}/{_maxReconnectAttempts})");

            _reconnectTimer = new System.Timers.Timer(_reconnectInterval);
            _reconnectTimer.Elapsed += async (sender, e) =>
            {
                StopReconnectTimer();
                Debug.WriteLine($"尝试重连 ({_currentReconnectAttempt}/{_maxReconnectAttempts})...");
                await ConnectInternalAsync(true);
            };
            _reconnectTimer.AutoReset = false;
            _reconnectTimer.Start();
        }

        // 停止重连定时器
        private void StopReconnectTimer()
        {
            if (_reconnectTimer != null)
            {
                _reconnectTimer.Stop();
                _reconnectTimer.Dispose();
                _reconnectTimer = null;
            }
        }

        // 示例：消息处理器
        private void HandleMessage(string message)
        {
            // 这里可以实现自定义的消息解析逻辑
            // 例如根据消息类型进行不同的处理
            Debug.WriteLine($"自定义消息处理: {message}");

            // 示例：解析特定格式的消息
            if (message.StartsWith("{"))
            {
                try
                {
                    //dynamic data = JsonConvert.DeserializeObject(message);
                    //string type = data.type;
                    //string content = data.content;

                    //Debug.WriteLine($"解析消息类型: {type}, 内容: {content}");

                    //// 根据消息类型进行不同处理
                    //if (type == "command")
                    //{
                    //    HandleCommand(content);
                    //}
                    //else if (type == "data")
                    //{
                    //    HandleData(content);
                    //}
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"解析JSON消息失败: {ex.Message}");
                }
            }
        }

        // 处理命令消息的示例方法
        private void HandleCommand(string command)
        {
            Debug.WriteLine($"处理命令: {command}");
            // 这里可以添加命令处理逻辑
        }

        // 处理数据消息的示例方法
        private void HandleData(string data)
        {
            Debug.WriteLine($"处理数据: {data}");
            // 这里可以添加数据处理逻辑
        }

        // 释放资源
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed)
                return;

            if (disposing)
            {
                _isManualDisconnect = true;
                StopPingTimer();
                StopReconnectTimer();

                if (_ws != null)
                {
                    if (_ws.IsAlive)
                        _ws.Close();
                    _ws = null;
                }

                _connectionSemaphore?.Dispose();
            }

            _isDisposed = true;
        }

        ~WebSocketClient()
        {
            Dispose(false);
        }
    }

}
